package door.smartlift.top.service.impl;

import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.thoughtworks.xstream.XStream;
import door.smartlift.top.common.constant.PayState;
import door.smartlift.top.common.constant.WxPayConstant;
import door.smartlift.top.common.utils.CollectionUtil;
import door.smartlift.top.common.utils.StringUtil;
import door.smartlift.top.common.utils.WXPayUtil;
import door.smartlift.top.common.utils.WxSession;
import door.smartlift.top.dao.*;
import door.smartlift.top.domain.*;
import door.smartlift.top.domain.base.BaseDateMembers;
import door.smartlift.top.domain.base.PageCommand;
import door.smartlift.top.domain.base.WxNotify;
import door.smartlift.top.domain.info.TransactionRecordInfo;
import door.smartlift.top.exception.MyDefineException;
import door.smartlift.top.service.ChairCmd;
import door.smartlift.top.service.IotOrderService;
import door.smartlift.top.service.SendLauncherChair;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.*;

/**
 *
 * @author Admin
 * @date 2018/4/2
 */
@Slf4j
@Service("iotOrderService")
public class IotOrderServiceImpl implements IotOrderService {

    @Autowired
    private IotOrderMapper iotOrderMapper;

    @Autowired
    private WxInfoMapper wxInfoMapper;

    @Autowired
    private IotBusinessMapper iotBusinessMapper;

    @Autowired
    private IotGoodsMapper iotGoodsMapper;

    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private IotDeviceMapper iotDeviceMapper;

    @Autowired
    private WxPayService wxPayService;



    @Override
    @Transactional
    public Map doUnifiedOrder(IotGoods iotGoods) throws Exception{

        IotGoods goods=this.iotGoodsMapper.selectByPrimaryKey(iotGoods.getId());

        IotOrder iotOrder=new IotOrder();

        iotOrder.setBid(goods.getBid());

        IotDeviceExample iotDeviceExample=new IotDeviceExample();

        iotDeviceExample.createCriteria().andDeviceNumEqualTo(iotGoods.getDeviceNum());

        //根据设备编号查询设备信息
        IotDevice iotDevice=this.iotDeviceMapper.selectByExample(iotDeviceExample).get(0);

        iotOrder.setDid(iotDevice.getId());
        iotOrder.setGname(goods.getGname());
        iotOrder.setDeviceSn(iotDevice.getDeviceSn());
        iotOrder.setDeviceType(iotDevice.getDeviceType());
        iotOrder.setDuration(goods.getDuration());
        iotOrder.setGprice(goods.getGprice());
        iotOrder.setParentId(iotDevice.getParentId());
//WxSession.getSessionId()
        WxUser wxUser=this.wxUserMapper.selectWxUserBySession(WxSession.getSessionId());
        iotOrder.setOpenid(wxUser.getOpenId());
        iotOrder.setUid(wxUser.getId());

        String orderCode=makeOrderCode(goods.getBid());
        iotOrder.setOrderSn(orderCode);
        iotOrder.setStatus(PayState.unpay.toString());

        String msg="微信用户:"+wxUser.getNickName()+"预下单"+goods.getGname()+",订单号:"+orderCode+",设备编号："+iotDevice.getDeviceNum();

        log.info(msg);
        this.iotOrderMapper.insertSelective(iotOrder);


        //WxInfo wxInfo=this.wxInfoMapper.selectWxInfo();
        Map data=new HashMap();
        data.put("body", goods.getGname());
        data.put("out_trade_no", orderCode);
        data.put("device_info", iotDevice.getDeviceSn());

        DecimalFormat df = new DecimalFormat("######0");
        Integer totalFee=Integer.parseInt(df.format(goods.getGprice()*100));
        data.put("appid","wxdb635c18c3a7ae7f");
        data.put("total_fee", String.valueOf(totalFee));
        data.put("spbill_create_ip", "123.12.12.123");
        //https://tq.tunnel.qydev.com/wx/notify
        data.put("notify_url", "https://door.smartlife.top/Fule/wx/notify");
        data.put("trade_type", "JSAPI");
        data.put("openid",wxUser.getOpenId());
        data.put("mch_id","1491308042");
        data.put("nonce_str",String.valueOf(System.currentTimeMillis()));
        data.put("device_info",iotDevice.getDeviceSn());
        data.put("attach",String.valueOf(goods.getPulse()));
        data.put("sign_type",String.valueOf(WxPayConstant.SignType.MD5));
        String sign=WXPayUtil.generateSignature(data,"6C5B77BC23A2BCAA5EE5AF7EB4938D5A", WxPayConstant.SignType.MD5);

        data.put("sign",sign);
        String reqBody = WXPayUtil.mapToXml(data);

        BasicHttpClientConnectionManager connManager=new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", SSLConnectionSocketFactory.getSocketFactory())
                        .build(),
                null,
                null,
                null
        );

        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();

        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");

        StringEntity postEntity = new StringEntity(reqBody, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        //httpPost.addHeader("User-Agent", "wxpay sdk java v1.0 " + config.getMchID());  // TODO: 很重要，用来检测 sdk 的使用情况，要不要加上商户信息？
        httpPost.setEntity(postEntity);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();

        String str=EntityUtils.toString(httpEntity, "UTF-8");

        XStream xstream = XStreamInitializer.getInstance();
        xstream.processAnnotations(WxPayUnifiedOrderResult.class);

        BaseWxPayResult result = (BaseWxPayResult)xstream.fromXML(str);
        result.setXmlString(str);

        WxPayUnifiedOrderResult orderResult=(WxPayUnifiedOrderResult)result;

        HashMap payResult1 = new HashMap();
        payResult1.put("appId", orderResult.getAppid());
        payResult1.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
        payResult1.put("nonceStr", UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32));
        payResult1.put("package", "prepay_id="+orderResult.getPrepayId());
        payResult1.put("signType",String.valueOf(WxPayConstant.SignType.MD5));

        String sign2=WXPayUtil.generateSignature(payResult1,"6C5B77BC23A2BCAA5EE5AF7EB4938D5A",WxPayConstant.SignType.MD5);

        payResult1.put("paySign",sign2);

        Map map=new HashMap();
        map.put("pay",payResult1);

        return map;





        //System.out.println(str);
        //微信下单
        /*WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest=new WxPayUnifiedOrderRequest();

        wxPayUnifiedOrderRequest.setBody(goods.getGname());
        wxPayUnifiedOrderRequest.setOutTradeNo(orderCode);
        //wxPayUnifiedOrderRequest.setDeviceInfo(iotDevice.getDeviceSn());
        //wxPayUnifiedOrderRequest.setAttach(String.valueOf(goods.getPulse()));

        DecimalFormat df = new DecimalFormat("######0");
        Integer totalFee=Integer.parseInt(df.format(goods.getGprice()*100));
        wxPayUnifiedOrderRequest.setTotalFee(totalFee);

        wxPayUnifiedOrderRequest.setSpbillCreateIp("116.62.146.53");
        wxPayUnifiedOrderRequest.setTradeType("JSAPI");
        wxPayUnifiedOrderRequest.setNonceStr(String.valueOf(System.currentTimeMillis()));

        //"https://door.smartlife.top/Fule/wx/notify"
        wxPayUnifiedOrderRequest.setNotifyUrl("https://tq.tunnel.qydev.com/wx/notify");
        wxPayUnifiedOrderRequest.setOpenid("olKsg0di3dF57OwbsLC91Gb7DllE");
        wxPayUnifiedOrderRequest.setSignType(WxPayConstants.SignType.MD5);

        WxPayMpOrderResult wxPayMpOrderResult=this.wxPayService.createOrder(wxPayUnifiedOrderRequest);

        System.out.println(wxPayMpOrderResult);
        return null;*/

        }

    private static Map<String,Boolean> cacheLauncherChairs=new HashMap<>();

    @Override
    public String conformWxPay(HttpServletRequest request)throws Exception {

        log.info("执行支付回调",request);
        String inputLine;
        String notityXml = "";

        try{
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            request.getReader().close();
        }catch (Exception e){

            e.printStackTrace();
            return responceWx(false);
        }

        log.info("接收到的报文：" + notityXml);

        try {

            WxPayOrderNotifyResult notifyResult=this.wxPayService.parseOrderNotifyResult(notityXml);
            String orderCode=notifyResult.getOutTradeNo();
            String wxOrderCode=notifyResult.getTransactionId();

            IotOrderExample iotOrderExample=new IotOrderExample();

            iotOrderExample.createCriteria().andOrderSnEqualTo(orderCode);

            IotOrder order=this.iotOrderMapper.selectByExample(iotOrderExample).get(0);


            if ("unpay".equals(order.getStatus())){

                log.info("支付回掉更新订单状态unpay---》pay,支付金额:"+order.getGprice()
                        +"---》 商户订单号："+orderCode+",微信订单号：" +wxOrderCode+",用户openId:"+order.getOpenid());

               IotOrder order2=new IotOrder();
                order2.setStatus(PayState.pay.toString());
                order2.setWxOrder(wxOrderCode);

                this.iotOrderMapper.updateByExampleSelective(order2,iotOrderExample);

                String attch=notifyResult.getAttach();



                String msg="启动设备---》" +
                            "设备ID:"+order.getDid()+",设备imei："+order.getDeviceSn()+",脉冲数："+attch+",按摩时长："+order.getDuration();

                log.info(msg);

                ChairCmd.launcherChairs(notifyResult.getDeviceInfo(), 50, 250, Integer.parseInt(attch), orderCode);


                return responceWx(true);

            }else {

                return responceWx(true);
            }



        } catch (Exception e) {

            log.info("支付回掉更新订单失败",e.getLocalizedMessage());
            e.printStackTrace();
            return responceWx(false);
        }

    }

    @Override
    public BaseDateMembers transactionRecord(PageCommand pageCommand,String payStatus,String deviceNum, String wxOrderCode) {

        Map params=new HashMap();
        params.put("payStatus",payStatus);
        params.put("deviceNum",deviceNum);
        params.put("wxOrder", wxOrderCode);

        Page<TransactionRecordInfo> page=PageHelper.startPage(pageCommand.getPageIndex(),pageCommand.getPageSize());

        List<TransactionRecordInfo> recordInfos=this.iotOrderMapper.selectTransactionRecord(params);

        int total=page.getPages();
        pageCommand.setPageTotal(page.getTotal());
        pageCommand.setTotalPages(total);

        return new BaseDateMembers<>(pageCommand,recordInfos);
    }

    public int updateOrderState(String orderCode, String wxOrderCode){

        IotOrderExample iotOrderExample=new IotOrderExample();

        iotOrderExample.createCriteria().andOrderSnEqualTo(orderCode);

        //获取时长
        int duration=this.iotOrderMapper.selectByExample(iotOrderExample).get(0).getDuration();

        IotOrder order=new IotOrder();
        order.setStatus(PayState.pay.toString());
        order.setWxOrder(wxOrderCode);

        this.iotOrderMapper.updateByExampleSelective(order, iotOrderExample);

        return duration;
    }

    private String responceWx(boolean result) {

        String resXml = "";
        if (result) {
            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                    + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
        } else {
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }

        return resXml;
    }



    public String makeOrderCode(Integer bid) {

        IotBusiness business=this.iotBusinessMapper.selectByPrimaryKey(bid);

        String pre = business.getPrefix();

        int tmp = new Random().nextInt(9999) % (9000) + 1000;
        String orderCode = pre + String.valueOf(System.currentTimeMillis()) + tmp;
        return orderCode;
    }


}
